package cz.muni.fi.pb138.eis_core;

import java.util.LinkedList;
import java.util.List;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQResultSequence;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Implementation of the ExpositionManager
 * over an XML Database (BaseX)
 * 
 * @author Jakub Senko
 */
public class ArtworkManagerImpl implements ArtworkManager
{
    DBTools dbt;
    
    public ArtworkManagerImpl(DBTools dbt)
    {
        if(dbt == null)
        {
            throw new NullPointerException();
        }
        this.dbt = dbt;
    }

    @Override
    public void create(ArtworkEntity entity) throws XQException
    {
        if(entity == null || "".equals(entity.getName()) || "".equals(entity.getAuthor()))
        {
            throw new NullPointerException();
        }
        
         
        
        Query q = dbt.getQuery();
        
        XQResultSequence xqrs = q.execute(dbt.getDoc()
                + "//lastId/artwork");

        xqrs.next();
        
        long id = Long.parseLong(xqrs.getNode().getTextContent()) + 1;

        dbt.executeQueryCommand("replace value of node "
                + dbt.getDoc() + "//lastId/artwork with '" + id + "'");
        
        dbt.executeQueryCommand(
            "insert node "
                + "<artwork id='" + id + "'>"
                    + "<name>" + dbt.sanitize(entity.getName()) + "</name>"
                    + "<author>" + dbt.sanitize(entity.getAuthor()) + "</author>"
                    + "<description>" + dbt.sanitize(entity.getDescription()) + "</description>"
                + "</artwork>"
            + " into " + dbt.getDoc()
            + "//exposition[@id = '" + entity.getExpositionId() + "']/artworks"
        );
        
        q.close();
        entity.setId(id);
        
    }

    @Override
    public ArtworkEntity getById(long id) throws XQException
    {              
        if(id <= 0) return null;
        
        Query q = dbt.getQuery();
        
        /* return statemement must be used because of
         * addition of the expositionId attribute
         */
        XQResultSequence xqrs = q.execute(
                "let $artwork := " + dbt.getDoc() + "//artwork[@id = '" + id + "'] "
                + "return "
                + "<artwork id='{$artwork/@id}' expositionId='{$artwork/../../@id}'>"
                + "{$artwork/name}"
                + "{$artwork/author}"
                + "{$artwork/description}"
                + "</artwork>");
        
        // does the entity exist?        
         if(xqrs.next() == false)
         {
             return null;
         }
       //System.out.println(xqrs.toString());
        ArtworkEntity e = parse(xqrs.getNode());
        
        q.close();
        
        return e;
    }

    @Override
    public List<ArtworkEntity> getAll() throws XQException
    {
        
        List<ArtworkEntity> list = new LinkedList<ArtworkEntity>();
        
        Query q = dbt.getQuery();
        
        XQResultSequence xqrs = q.execute(
                "for $artwork in " + dbt.getDoc() + "//artwork "
                + "return "
                + "<artwork id='{$artwork/@id}' expositionId='{$artwork/../../@id}'>"
                + "{$artwork/name}"
                + "{$artwork/author}"
                + "{$artwork/description}"
                + "</artwork>");
        
        xqrs.next();
        
        while(xqrs.next())
        {
            list.add(parse(xqrs.getNode()));    
        }
        q.close();
        
        return list;
    }

 
    @Override
    public boolean delete(ArtworkEntity entity) throws XQException
    {
        if(entity == null)
        {
            throw new NullPointerException();
        }
        
        //does the entity exist?
         if(getById(entity.getId()) == null)
         {
             return false;
         }
        
        dbt.executeQueryCommand(
                "delete nodes " + dbt.getDoc()
                + "//artwork[@id = '" + entity.getId() + "']");
        
        return true;
    }
    
    /**
     * This method parses data and creates
     * a new ArtworkEntity from an XML Node
     * (retrieved from the database).
     *
     */
     // Template:
     // <artwork id="ID" expositionId="EXPOSITION_ID">
     //  <name>NAME</name>
     //  <author>AUTHOR</author>
     //  <description>DESCRIPTION</description>
     // </artwork>
    private ArtworkEntity parse(Node node)
    {
        Element element = (Element) node;
        
        ArtworkEntity e = new ArtworkEntity();

        e.setId(Long.parseLong( element.getAttribute("id")));
        
        e.setExpositionId(Long.parseLong( element.getAttribute("expositionId")));
        
        e.setName( element.getElementsByTagName("name").item(0).getTextContent() );
        
        e.setAuthor( element.getElementsByTagName("author").item(0).getTextContent() );
        
        e.setDescription( element.getElementsByTagName("description").item(0).getTextContent() );
        
        return e;
    }

}
